﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;


namespace 测量大师
{
    //计算类，内含多种计算函数，目前已有
    public class calculator
    {
        //利用坐标方位角算delatx delaty
        public static double CalDelatX(Double X, string angle)
        {

            double DelatX = X * Math.Cos(Angle.dmstorad(angle));
            return DelatX;
        }
        public static double CalDelatY(Double Y, string angle)
        {
            double DelatY = Y * Math.Sin(Angle.dmstorad(angle));
            return DelatY;
        }
        public static double delta(Double d1, double d2)
        {
            return d1 - d2;
        }
        //利用已知坐标方位角和转折角推算未知坐标方位角
        public static string CalAz(string Az1, string angle ,int judge )
        {
            double[] a = new double[3];
            double[] b = new double[3];

            string[] s1 = Az1.Split(new char[3] { '°', '′', '″' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < a.Length; i++)
                a[i] = Convert.ToDouble(s1[i]);

            string[] s2 = angle.Split(new char[3] { '°', '′', '″' }, StringSplitOptions.RemoveEmptyEntries);
            for (int i = 0; i < b.Length; i++)
                b[i] = Convert.ToDouble(s2[i]);
            if (judge == 0)
            {
                for (int i = 2; i >= 1; i--)
                {
                    a[i] = a[i] + b[i];
                    if (a[i] >= 60)
                    {
                        a[i] = a[i] - 60;
                        a[i - 1] += 1;
                    }
                }
                a[0] = a[0] + b[0] - 180;
                if (a[0] < 0)
                    a[0] += 360;
                if (a[0] >= 360)
                    a[0] -= 360;
            }
            else
            {
                for (int i = 2; i >= 1; i--)
                {
                    a[i] = a[i] - b[i];
                    if (a[i] >= 60)
                    {
                        a[i] = a[i] - 60;
                        a[i - 1] += 1;
                    }
                    if (a[i] < 0)
                    {
                        a[i] = a[i] + 60;
                        a[i - 1] -= 1;
                    }
                }
                a[0] = a[0] - b[0] + 180;
                if (a[0] < 0)
                    a[0] += 360;
                if (a[0] >= 360)
                    a[0] -= 360;
            }
            string s = Convert.ToString(a[0]) + "°" + Convert.ToString(a[1]) + "′" + Convert.ToString(a[2]) + "″";
            return s;
        }
        //利用坐标反算坐标方位角
        public static string XYtoAZ(double X1, double X2, double Y1, double Y2)
        {
            double detaX = X2 - X1;
            double detaY = Y2 - Y1;
            double a = Math.Atan2(Math.Abs(Y2 - Y1), Math.Abs(X2 - X1));
            if (detaX > 0 && detaY > 0)
                a = a + 0;
            if (detaX < 0 && detaY > 0)
                a = Math.PI - a;
            if (detaX > 0 && detaY < 0)
                a = 2 * Math.PI - a;
            if (detaX < 0 && detaY < 0)
                a = Math.PI + a;
            if (a < 0)
                a = 2 * Math.PI + a;
            if (a > 2 * Math.PI)
                a = a - 2 * Math.PI;
            //将弧度转化为角度
            return Angle.radtodms(a);
        }
        //角度平差
        public static string[] Corangle(string[] a, out string[] gz , out double DeltaAngle)
        {
            double[] D = new double[a.Length];
            double[] F = new double[a.Length];
            double[] M = new double[a.Length];

            for (int i = 0; i < a.Length; i++)//将角度拆分，度储存在D[]中，分储存在F[]，秒储存在M[]中。
            {
                string[] s = a[i].Split(new char[3] { '°', '′', '″' }, StringSplitOptions.RemoveEmptyEntries);
                D[i] = Convert.ToDouble(s[0]);
                F[i] = Convert.ToDouble(s[1]);
                M[i] = Convert.ToDouble(s[2]);
            }
            double SumM = 0;
            double SumF = 0;
            double SumD = 0;

            for (int i = 0; i < a.Length; i++)//将角度相加
            {
                SumM += M[i];
                SumF += F[i];
                SumD += D[i];
                while (SumM >= 60)
                {
                    SumF += 1;
                    SumM -= 60;
                }
                while (SumF >= 60)
                {
                    SumD += 1;
                    SumF -= 60;
                }
            }
            double zhen = (a.Length - 2) * 180;

            double gai = ((zhen - SumD) * 60 - SumF) * 60 - SumM;
            int zhchu = (int)(gai / a.Length);
            int quyu = (int)(gai % a.Length);
            for (int i = 0; i < a.Length; i++)
            {
                M[i] += zhchu;
                while (M[i] >= 60)
                {
                    F[i] += 1;
                    M[i] -= 60;
                }
                while (M[i] < 0)
                {
                    F[i] -= 1;
                    M[i] += 60;
                }

                while (F[i] >= 60)
                {
                    D[i] += 1;
                    F[i] -= 60;
                }
                while (F[i] < 0)
                {
                    D[i] -= 1;
                    F[i] += 60;
                }
                while (D[i] < 0)
                {
                    D[i] += 365;
                }

            }

            int j = 0;
            int k = quyu;
            while (k > 0)
            {
                M[j] += 1;
                j += 1;
                k -= 1;
                if (M[j] >= 60)
                    F[j] += 1;
                if(M[j]<0)
                {
                    F[j] -= 1;
                    M[j] += 60;
                }    
                if (F[j] >= 60)
                    D[j] += 1;
                if (F[j] < 0)
                {
                    D[j] -= 1;
                    F[j] += 60;
                }
                if (D[j] < 0)
                {
                    D[j] += 365;
                }
            }

            string[] ss = new string[a.Length];//ss[]储存的是改正后的值。
            for (int i = 0; i < a.Length; i++)
            {
                ss[i] = Convert.ToString(D[i]) + "°" + Convert.ToString(F[i]) + "′" + Convert.ToString(M[i]) + "″";
            }

            string[] gg = new string[a.Length];//gg[]储存改正数。
            for (int i = 0; i < quyu; i++)
            {
                gg[i] = Convert.ToString(zhchu + 1);
            }
            for (int i = quyu; i < a.Length; i++)
            {
                gg[i] = Convert.ToString(zhchu);
            }
            gz = gg;
            DeltaAngle = Math.Abs(gai);
            return ss;
        }
        //deltaX Y平差计算器
        public static double[] XYPingCha(double[] bianLiang, double[] bianChang, out double[] gaiZhengShu, out double Ssum , out double Deltasum)
        {
            double sum1 = 0; //sum1储存△X或△Y的和
            double sum2 = 0; //sum2储存边长的和
            double sum3 = 0; //sum3储存进行一轮分配后改正数的和

            for (int i = 0; i < bianLiang.Length; i++) //进行deltaX或Y求和
            {
                sum1 += bianLiang[i];
            }
            for (int i = 0; i < bianChang.Length; i++)//进行边长求和
            {
                sum2 += bianChang[i];
            }

            double[] delta = new double[bianLiang.Length];
            gaiZhengShu = new double[bianLiang.Length];

            int[] a = new int[bianLiang.Length]; //a数组储存保留三位小数后的改正数。
            for (int i = 0; i < bianLiang.Length; i++) //进行第一轮的按比例分配               
            {
                a[i] = (int)(sum1 * bianChang[i] / sum2 * 1000);
                gaiZhengShu[i] = -(double)a[i] / 1000;
                delta[i] = bianLiang[i] + gaiZhengShu[i];

            }

            for (int i = 0; i < bianChang.Length; i++)//进行改正数求和
            {
                sum3 += gaiZhengShu[i];
            }
            double cha = sum1 + sum3;//cha储存剩余要分配的量

            double[] b = new double[bianLiang.Length];//将边长备份到b数组中，方便进行排序
            for (int i = 0; i < bianChang.Length; i++)
            {
                b[i] = bianChang[i];
            }

            int[] c = new int[bianLiang.Length];//c数组按大小储存边长的编号。
            for (int i = 0; i < bianChang.Length; i++)
            {
                double max = b[0];
                c[i] = 0;
                for (int j = 1; j < bianChang.Length; j++)
                {
                    if (b[j] > max)
                        max = b[j];
                    c[i] = j;
                }
                b[c[i]] = 0;
            }
            //进行最后多余量的分配。
            if (cha < 0)
            {
                int i = 0;
                while (cha < 0)
                {
                    delta[c[i]] -= 0.001;
                    cha += 0.001;
                    gaiZhengShu[c[i]] += 0.001;
                    i += 1;
                }
            }
            if (cha > 0)
            {
                int i = 0;
                while (cha > 0)
                {
                    delta[c[i]] += 0.001;
                    cha -= 0.001;
                    gaiZhengShu[i] -= 0.001;
                    i += 1;
                }
            }
            Ssum = sum2;
            Deltasum = Math.Abs(sum1);
            return delta;
        }
        // 右角到左角转换的函数
        public static string[] LAtoRA(string[] RA)
        {
            string[] LA = new string[RA.Length];
            int num = 0;
            foreach (var item in RA)
            {
                string[] s1 = item.Split(new char[3] { '°', '′', '″' }, StringSplitOptions.RemoveEmptyEntries);
                double[] a = new double[s1.Length];
                for (int i = 0; i < a.Length; i++)
                    a[i] = Convert.ToDouble(s1[i]);
                a[2] = 60 - a[2];
                a[1] = 59 - a[1];
                a[0] = 359 - a[0];
                LA[num] = Convert.ToString(a[0]) + "°" + Convert.ToString(a[1]) + "′" + Convert.ToString(a[2]) + "″";
            }
            return LA;
        }
        // 右角到左角转换的函数
        public static string LAtoRA1(string RA)
        {
            string LA ;
                string[] s1 = RA.Split(new char[3] { '°', '′', '″' }, StringSplitOptions.RemoveEmptyEntries);
                double[] a = new double[3];
                for (int i = 0; i < a.Length; i++)
                    a[i] = Convert.ToDouble(s1[i]);
                a[2] = 60 - a[2];
                a[1] = 59 - a[1];
                a[0] = 359 - a[0];
                LA = Convert.ToString(a[0]) + "°" + Convert.ToString(a[1]) + "′" + Convert.ToString(a[2]) + "″";
            
            return LA;
        }
        //附合导线方位角简易平差
        public static string[] FHPingChaAZ(string[] AZ, string EndAZ, string EndTrueAz , out int DeltaAngle)
        {

            string[] PAZ = (string[])AZ.Clone();
            string[] EA = new string[3];
            string[] ETA = new string[3];
            EA = EndAZ.Split(new char[3] { '°', '′', '″' }, StringSplitOptions.RemoveEmptyEntries);
            ETA = EndTrueAz.Split(new char[3] { '°', '′', '″' }, StringSplitOptions.RemoveEmptyEntries);

            int IEA = int.Parse(EA[0]) * 3600 + int.Parse(EA[1]) * 60 + int.Parse(EA[2]);
            int IETA = int.Parse(ETA[0]) * 3600 + int.Parse(ETA[1]) * 60 + int.Parse(ETA[2]);
            int VA = IETA - IEA;
            DeltaAngle = VA;
            int perV = VA / AZ.Length;
            int yuV = VA % AZ.Length;

            double[] D = new double[AZ.Length];
            double[] F = new double[AZ.Length];
            double[] M = new double[AZ.Length];

            for (int i = 0; i < AZ.Length; i++)//将角度拆分，度储存在D[]中，分储存在F[]，秒储存在M[]中。
            {
                string[] s = AZ[i].Split(new char[3] { '°', '′', '″' }, StringSplitOptions.RemoveEmptyEntries);
                D[i] = Convert.ToDouble(s[0]);
                F[i] = Convert.ToDouble(s[1]);
                M[i] = Convert.ToDouble(s[2]);
            }
            // 每个角度要分配一定的闭合差
            for (int i = 0; i < AZ.Length; i++)
            {
                M[i] += (double)perV;
                while (M[i] >= 60)
                {
                    M[i] -= 60;
                    F[i] += 1;
                }
                while (M[i] < 0)              
                {
                    M[i] += 60;
                    if (F[i] == 0)
                    {
                        if (D[i] == 0) //考虑到最极端的情况0度0分几秒，不够减
                        {
                            D[i] += 359;
                            F[i] += 59;
                        }
                        else
                        {
                            D[i] -= 1;
                            F[i] += 59;
                        }
                    }
                    else
                    {
                        F[i] -= 1;
                    }
                }
                while (F[i] >= 60)
                {
                    F[i] -= 60;
                    D[i] += 1;
                }
                while (F[i] < 0)
                {
                    F[i] += 60;
                    if (D[i] == 0)
                    {
                        D[i] += 365;
                    }
                    else
                    {
                        D[i] -= 1;
                    }
                }
            }
            //处理余数
            int num = 0;
            while (yuV > 0)
            {
                M[num] += VA / Math.Abs(VA);
                while (M[num] >= 60)
                {
                    M[num] -= 60;
                    F[num] += 1;
                }
                while (M[num] < 0)
                {
                    M[num] += 60;
                    if (F[num] == 0)
                    {
                        if (D[num] == 0) //考虑到最极端的情况0度0分几秒，不够减
                        {
                            D[num] += 359;
                            F[num] += 59;
                            M[num] += 60;
                        }
                        else
                        {
                            D[num] -= 1;
                            F[num] += 59;
                        }
                    }
                    else
                    {
                        F[num] -= 1;
                    }
                }

                num++;
                yuV--;
            }
            //产生改正后的方位角
            for (int i = 0; i < AZ.Length; i++)
            {
                PAZ[i] = Convert.ToString(D[i]) + "°" + Convert.ToString(F[i]) + "′" + Convert.ToString(M[i]) + "″";
            }

            
            return PAZ;
        }
            //附和导线DX DY简易平差
        public static double[] FHPingChaDXDY(double[] Delta, double[] S, double EndDelta, double EndTDelta , out Double Ssum ,out Double Deltasum)
            {
                double[] PDelta = new double[Delta.Length];
                //边长求和
                double ssum = 0;
                foreach (var item in S)
                {
                    ssum += item;
                }

                double DeltaDelta = EndTDelta - EndDelta;
                for (int i = 0; i < PDelta.Length; i++)
                {
                    PDelta[i] = S[i] / ssum * Delta[i];
                }
            Ssum = ssum;
            Deltasum = DeltaDelta;
                return PDelta;
            }
            //创建新的方法，用于创建固定格式的表格

            //闭合导线
        public static void CreateTable(DataTable dt)
            {
                DataColumn p方位角 = new DataColumn("方位角", typeof(string));
                DataColumn p边长 = new DataColumn("边长", typeof(Double));
                DataColumn pDX = new DataColumn("DX", typeof(Double));
                DataColumn pDY = new DataColumn("DY", typeof(Double));
                DataColumn pX = new DataColumn("X", typeof(Double));
                DataColumn pY = new DataColumn("Y", typeof(Double));
                DataColumn 点名 = new DataColumn("点名", typeof(string));
                DataColumn 转折角 = new DataColumn("转折角", typeof(string));
                DataColumn 角度改正数 = new DataColumn("角度改正数", typeof(string));
                DataColumn DX改正数 = new DataColumn("DX改正数", typeof(double));
                DataColumn DY改正数 = new DataColumn("DY改正数", typeof(double));
                DataColumn 改正后转折角 = new DataColumn("改正后转折角", typeof(string));
                DataColumn 改正后DX = new DataColumn("改正后DX", typeof(double));
                DataColumn 改正后DY = new DataColumn("改正后DY", typeof(double));

                dt.Columns.Add(点名);
                dt.Columns.Add(转折角);
                dt.Columns.Add(改正后转折角);
                dt.Columns.Add(p方位角);
                dt.Columns.Add(p边长);
                dt.Columns.Add(pDX);
                dt.Columns.Add(pDY);
                dt.Columns.Add(改正后DX);
                dt.Columns.Add(改正后DY);
                dt.Columns.Add(pX);
                dt.Columns.Add(pY);


            }

            //支导线
        public static DataTable CreateZhiTable(DataTable dt)
            {
                DataColumn p方位角 = new DataColumn("方位角", typeof(string));
                DataColumn p边长 = new DataColumn("边长", typeof(Double));
                DataColumn pDX = new DataColumn("DX", typeof(Double));
                DataColumn pDY = new DataColumn("DY", typeof(Double));
                DataColumn pX = new DataColumn("X", typeof(Double));
                DataColumn pY = new DataColumn("Y", typeof(Double));
                DataColumn 点名 = new DataColumn("点名", typeof(string));
                DataColumn 转折角 = new DataColumn("转折角", typeof(string));

                dt.Columns.Add(点名);
                dt.Columns.Add(转折角);
                dt.Columns.Add(p方位角);
                dt.Columns.Add(p边长);
                dt.Columns.Add(pDX);
                dt.Columns.Add(pDY);
                dt.Columns.Add(pX);
                dt.Columns.Add(pY);


                return dt;
            }

            //附合导线
        public static DataTable CreateFHTabel(DataTable dt)
            {
                DataColumn p方位角 = new DataColumn("方位角", typeof(string));
                DataColumn p边长 = new DataColumn("边长", typeof(Double));
                DataColumn pDX = new DataColumn("DX", typeof(Double));
                DataColumn pDY = new DataColumn("DY", typeof(Double));
                DataColumn pX = new DataColumn("X", typeof(Double));
                DataColumn pY = new DataColumn("Y", typeof(Double));
                DataColumn 点名 = new DataColumn("点名", typeof(string));
                DataColumn 转折角 = new DataColumn("转折角", typeof(string));
                DataColumn 改正后方位角 = new DataColumn("改正后方位角", typeof(string));
                DataColumn 改正后DX = new DataColumn("改正后DX", typeof(Double));
                DataColumn 改正后DY = new DataColumn("改正后DY", typeof(Double));


                dt.Columns.Add(点名);
                dt.Columns.Add(转折角);
                dt.Columns.Add(p方位角);
                dt.Columns.Add(p边长);
                dt.Columns.Add(pDX);
                dt.Columns.Add(pDY);
                dt.Columns.Add(改正后方位角);
                dt.Columns.Add(改正后DX);
                dt.Columns.Add(改正后DY);
                dt.Columns.Add(pX);
                dt.Columns.Add(pY);

                return dt;
            }


        //画图的方法
        public static void DrawCrosses(Point[] points, Graphics g, string[]Name, double[] TPX , double[]TPY)
        {
            Pen pen = new Pen(Color.Red)
            {
                Width = 2
            };
            int num = points.Length;
            for (int i = 0; i < num - 1; i++)
            {
                g.DrawLine(pen, points[i], points[i + 1]);
                string str = string.Format("{0},坐标({1:f3},{2:f3})", Name[i], TPX[i], TPY[i]);
                g.DrawString(str, new Font("Verdana", 10), new SolidBrush(Color.Tomato), points[i].X + 5, points[i].Y + 5);
            }
            

            

        }




    }
}

